const toString = Object.prototype.toString;

export type KeyVal = { [key: string]: unknown };

export const isObject = (val: unknown) => {
  return val !== null && typeof val === "object";
};

export const isDate = (val: unknown) => {
  return toString.call(val) === "[object Date]";
};

export const isURLSearchParams = (val: unknown) => {
  return (
    typeof URLSearchParams !== "undefined" && val instanceof URLSearchParams
  );
};

export const isArray = (val: unknown) => {
  return toString.call(val) === "[object Array]";
};

export const forEach = (obj: KeyVal | unknown[], fn: Function) => {
  // Don't bother if no value provided
  if (obj === null || typeof obj === "undefined") {
    return;
  }

  // Force an array if not already something iterable
  if (typeof obj !== "object") {
    /*eslint no-param-reassign:0*/
    obj = [obj];
  }

  if (isArray(obj)) {
    const arr = obj as unknown[];
    // Iterate over array values
    for (var i = 0, l = arr.length; i < l; i++) {
      fn.call(null, arr[i], i, obj);
    }
  } else {
    const o = obj as KeyVal;
    // Iterate over object keys
    for (var key in o) {
      if (Object.prototype.hasOwnProperty.call(o, key)) {
        fn.call(null, o[key], key, obj);
      }
    }
  }
};
